package com.hbnu.reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;

/**
 * @author kittychen
 * @since 2025-10-15 15:16
 */
public class ReflectDemo {
    public static void main(String[] args) throws Exception {
        // 1、获取字节码对象
        // 1.1、通过类名获取
        Class<Person> personClass = Person.class;

        // 1.2、通过对象获取
        Person person = new Person();
        Class<? extends Person> personClass1 = person.getClass();

        // 1.3、通过字符串获取
        Class<?> personClass2 = Class.forName("com.hbnu.reflect.Person");

        // 2、获取构造方法
        System.out.println("=========================获取构造方法=========================");
        System.out.println("2.1、获取所有的公共构造方法");
        Constructor<?>[] constructors = personClass.getConstructors();
        System.out.println("所有公共构造方法的个数：" + constructors.length + "，分别是：");
        for (Constructor<?> constructor : constructors) {
            System.out.print("构造方法的名字：" + constructor.getName());
            Parameter[] parameters = constructor.getParameters();
            System.out.print("，参数个数：" + parameters.length + "，参数类型：");
            for (Parameter parameter : parameters) {
                System.out.print(parameter.getType().getName() + "\t");
            }
            System.out.println();
        }
        System.out.println("2.2、获取所有的构造方法(包括私有的构造方法)");
        Constructor<?>[] declaredConstructors = personClass.getDeclaredConstructors();
        System.out.println("所有构造方法的个数：" + declaredConstructors.length + "，分别是：");
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.print("构造方法的名字：" + declaredConstructor.getName());
            Parameter[] parameters = declaredConstructor.getParameters();
            System.out.print("，参数个数：" + parameters.length + "，参数类型：");
            for (Parameter parameter : parameters) {
                System.out.print(parameter.getType().getName() + "\t");
            }
            System.out.println();
        }
        System.out.println("2.3、获取指定的公共构造方法");
        Constructor<Person> constructor = personClass.getConstructor(String.class, int.class);
        // 通过构造方法创建实例对象
        Person person1 = constructor.newInstance("张三", 18);
        System.out.println("通过反射的方式创建的实例对象：" + person1);

        System.out.println("=========================获取成员属性=========================");
        Person person2 = (Person) personClass2.newInstance();
        System.out.println("3.1、获取所有的公共成员属性");
        Field[] fields = personClass.getFields();
        System.out.println("所有公共成员属性的个数：" + fields.length + "，分别是：");
        for (Field field : fields) {
            System.out.println("属性名：" + field.getName() + "\t属性类型：" + field.getType().getName());
        }
        System.out.println("3.2、获取所有的成员属性(包括私有的成员属性)");
        Field[] declaredFields = personClass.getDeclaredFields();
        System.out.println("所有成员属性的个数：" + declaredFields.length + "，分别是：");
        for (Field declaredField : declaredFields) {
            System.out.println("属性名：" + declaredField.getName() + "\t属性类型：" + declaredField.getType().getName());
        }
        System.out.println("3.3、获取指定的公共成员属性");
        Field salary = personClass.getField("salary");
        salary.set(person2, 10000);
        System.out.println("通过反射的方式给公共成员属性赋值：" + person2.getSalary());
        System.out.println("3.4、获取指定的成员属性（私有成员属性并赋值）");
        Field name = personClass.getDeclaredField("name");
        name.setAccessible(true); // 设置为可访问
        name.set(person2, "张三");
        System.out.println("通过反射的方式给私有成员属性赋值：" + person2.getName());

        System.out.println("=========================获取成员方法=========================");
        System.out.println("4.1、获取所有的公共成员方法（包括从父类继承过来的方法）");
        Method[] methods = personClass.getMethods();
        System.out.println("所有公共成员方法的个数：" + methods.length + "，分别是：");
        for (Method method : methods) {
            System.out.print("方法名：" + method.getName() + "\t返回值类型：" + method.getReturnType().getName());
            Parameter[] parameters = method.getParameters();  // 获取参数列表
            System.out.print("，参数个数：" + parameters.length + "，参数类型：");
            for (Parameter parameter : parameters) {
                System.out.print(parameter.getType().getName() + "\t");
            }
            System.out.println();
        }
        System.out.println("4.2、获取所有的成员方法(包括私有的，不包括从父类继承过来的方法)");
        Method[] declaredMethods = personClass.getDeclaredMethods();
        System.out.println("所有成员方法的个数：" + declaredMethods.length + "，分别是：");
        for (Method declaredMethod : declaredMethods) {
            System.out.print("方法名：" + declaredMethod.getName() + "\t返回值类型：" + declaredMethod.getReturnType().getName());
            Parameter[] parameters = declaredMethod.getParameters();  // 获取参数列表
            System.out.print("，参数个数：" + parameters.length + "，参数类型：");
            for (Parameter parameter : parameters) {
                System.out.print(parameter.getType().getName() + "\t");
            }
            System.out.println();
        }
        System.out.println("4.3、获取指定的公共成员方法，并调用方法");
        Method method1 = personClass.getMethod("method1");
        String result = (String) method1.invoke(person2);
        System.out.println("通过反射的方式调用公共成员方法：" + result);
        System.out.println("4.4、获取指定的成员方法，并调用方法（私有方法）");
        Method method2 = personClass.getDeclaredMethod("method2", String.class);
        method2.setAccessible(true); // 设置为可访问
        method2.invoke(person2, "李四");

    }
}
